
<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Filesystem &#8212; libuv documentation</title>
    <link rel="stylesheet" href="../_static/nature.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script src="../_static/jquery.js"></script>
    <script src="../_static/underscore.js"></script>
    <script src="../_static/doctools.js"></script>
    <script src="../_static/language_data.js"></script>
    <link rel="shortcut icon" href="../_static/favicon.ico"/>
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="next" title="Networking" href="networking.html" />
    <link rel="prev" title="Basics of libuv" href="basics.html" /> 
  </head><body>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="networking.html" title="Networking"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="basics.html" title="Basics of libuv"
             accesskey="P">previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="../index.html">libuv 1.31.0 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../guide.html" accesskey="U">User guide</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Filesystem</a></li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <div class="section" id="filesystem">
<h1>Filesystem<a class="headerlink" href="#filesystem" title="Permalink to this headline">¶</a></h1>
<p>Simple filesystem read/write is achieved using the <code class="docutils literal notranslate"><span class="pre">uv_fs_*</span></code> functions and the
<code class="docutils literal notranslate"><span class="pre">uv_fs_t</span></code> struct.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The libuv filesystem operations are different from <a class="reference internal" href="networking.html"><span class="doc">socket operations</span></a>. Socket operations use the non-blocking operations provided
by the operating system. Filesystem operations use blocking functions
internally, but invoke these functions in a <a class="reference external" href="http://docs.libuv.org/en/v1.x/threadpool.html#thread-pool-work-scheduling">thread pool</a> and notify
watchers registered with the event loop when application interaction is
required.</p>
</div>
<p>All filesystem functions have two forms - <em>synchronous</em> and <em>asynchronous</em>.</p>
<p>The <em>synchronous</em> forms automatically get called (and <strong>block</strong>) if the
callback is null. The return value of functions is a <a class="reference internal" href="basics.html#libuv-error-handling"><span class="std std-ref">libuv error code</span></a>. This is usually only useful for synchronous calls.
The <em>asynchronous</em> form is called when a callback is passed and the return
value is 0.</p>
<div class="section" id="reading-writing-files">
<h2>Reading/Writing files<a class="headerlink" href="#reading-writing-files" title="Permalink to this headline">¶</a></h2>
<p>A file descriptor is obtained using</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span> <span class="n">uv_fs_open</span><span class="p">(</span><span class="n">uv_loop_t</span><span class="o">*</span> <span class="n">loop</span><span class="p">,</span> <span class="n">uv_fs_t</span><span class="o">*</span> <span class="n">req</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">path</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="kt">int</span> <span class="n">mode</span><span class="p">,</span> <span class="n">uv_fs_cb</span> <span class="n">cb</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">flags</span></code> and <code class="docutils literal notranslate"><span class="pre">mode</span></code> are standard
<a class="reference external" href="http://man7.org/linux/man-pages/man2/open.2.html">Unix flags</a>.
libuv takes care of converting to the appropriate Windows flags.</p>
<p>File descriptors are closed using</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span> <span class="n">uv_fs_close</span><span class="p">(</span><span class="n">uv_loop_t</span><span class="o">*</span> <span class="n">loop</span><span class="p">,</span> <span class="n">uv_fs_t</span><span class="o">*</span> <span class="n">req</span><span class="p">,</span> <span class="n">uv_file</span> <span class="n">file</span><span class="p">,</span> <span class="n">uv_fs_cb</span> <span class="n">cb</span><span class="p">)</span>
</pre></div>
</div>
<p>Filesystem operation callbacks have the signature:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">void</span> <span class="nf">callback</span><span class="p">(</span><span class="n">uv_fs_t</span><span class="o">*</span> <span class="n">req</span><span class="p">);</span>
</pre></div>
</div>
<p>Let’s see a simple implementation of <code class="docutils literal notranslate"><span class="pre">cat</span></code>. We start with registering
a callback for when the file is opened:</p>
<p class="rubric">uvcat/main.c - opening a file</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">on_open</span><span class="p">(</span><span class="n">uv_fs_t</span> <span class="o">*</span><span class="n">req</span><span class="p">)</span> <span class="p">{</span>
    <span class="o">//</span> <span class="n">The</span> <span class="n">request</span> <span class="n">passed</span> <span class="n">to</span> <span class="n">the</span> <span class="n">callback</span> <span class="ow">is</span> <span class="n">the</span> <span class="n">same</span> <span class="k">as</span> <span class="n">the</span> <span class="n">one</span> <span class="n">the</span> <span class="n">call</span> <span class="n">setup</span>
    <span class="o">//</span> <span class="n">function</span> <span class="n">was</span> <span class="n">passed</span><span class="o">.</span>
<span class="hll">    <span class="k">assert</span><span class="p">(</span><span class="n">req</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">open_req</span><span class="p">);</span>
</span>    <span class="k">if</span> <span class="p">(</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="hll">        <span class="n">iov</span> <span class="o">=</span> <span class="n">uv_buf_init</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
</span><span class="hll">        <span class="n">uv_fs_read</span><span class="p">(</span><span class="n">uv_default_loop</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">read_req</span><span class="p">,</span> <span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span><span class="p">,</span>
</span>                   <span class="o">&amp;</span><span class="n">iov</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">on_read</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;error opening file: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">uv_strerror</span><span class="p">((</span><span class="nb">int</span><span class="p">)</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span><span class="p">));</span>
    <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The <code class="docutils literal notranslate"><span class="pre">result</span></code> field of a <code class="docutils literal notranslate"><span class="pre">uv_fs_t</span></code> is the file descriptor in case of the
<code class="docutils literal notranslate"><span class="pre">uv_fs_open</span></code> callback. If the file is successfully opened, we start reading it.</p>
<p class="rubric">uvcat/main.c - read callback</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">on_read</span><span class="p">(</span><span class="n">uv_fs_t</span> <span class="o">*</span><span class="n">req</span><span class="p">)</span> <span class="p">{</span>
<span class="hll">    <span class="k">if</span> <span class="p">(</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span>        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Read error: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">uv_strerror</span><span class="p">(</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">uv_fs_t</span> <span class="n">close_req</span><span class="p">;</span>
        <span class="o">//</span> <span class="n">synchronous</span>
<span class="hll">        <span class="n">uv_fs_close</span><span class="p">(</span><span class="n">uv_default_loop</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">close_req</span><span class="p">,</span> <span class="n">open_req</span><span class="o">.</span><span class="n">result</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span>
</span>    <span class="p">}</span>
    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">iov</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span><span class="p">;</span>
<span class="hll">        <span class="n">uv_fs_write</span><span class="p">(</span><span class="n">uv_default_loop</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">write_req</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">iov</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">on_write</span><span class="p">);</span>
</span>    <span class="p">}</span>
<span class="p">}</span>

</pre></div>
</td></tr></table></div>
<p>In the case of a read call, you should pass an <em>initialized</em> buffer which will
be filled with data before the read callback is triggered. The <code class="docutils literal notranslate"><span class="pre">uv_fs_*</span></code>
operations map almost directly to certain POSIX functions, so EOF is indicated
in this case by <code class="docutils literal notranslate"><span class="pre">result</span></code> being 0. In the case of streams or pipes, the
<code class="docutils literal notranslate"><span class="pre">UV_EOF</span></code> constant would have been passed as a status instead.</p>
<p>Here you see a common pattern when writing asynchronous programs. The
<code class="docutils literal notranslate"><span class="pre">uv_fs_close()</span></code> call is performed synchronously. <em>Usually tasks which are
one-off, or are done as part of the startup or shutdown stage are performed
synchronously, since we are interested in fast I/O when the program is going
about its primary task and dealing with multiple I/O sources</em>. For solo tasks
the performance difference usually is negligible and may lead to simpler code.</p>
<p>Filesystem writing is similarly simple using <code class="docutils literal notranslate"><span class="pre">uv_fs_write()</span></code>.  <em>Your callback
will be triggered after the write is complete</em>.  In our case the callback
simply drives the next read. Thus read and write proceed in lockstep via
callbacks.</p>
<p class="rubric">uvcat/main.c - write callback</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7
8
9</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<span class="n">void</span> <span class="n">on_write</span><span class="p">(</span><span class="n">uv_fs_t</span> <span class="o">*</span><span class="n">req</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Write error: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">uv_strerror</span><span class="p">((</span><span class="nb">int</span><span class="p">)</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">result</span><span class="p">));</span>
    <span class="p">}</span>
<span class="hll">    <span class="k">else</span> <span class="p">{</span>
</span>        <span class="n">uv_fs_read</span><span class="p">(</span><span class="n">uv_default_loop</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">read_req</span><span class="p">,</span> <span class="n">open_req</span><span class="o">.</span><span class="n">result</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">iov</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">on_read</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Due to the way filesystems and disk drives are configured for performance,
a write that ‘succeeds’ may not be committed to disk yet.</p>
</div>
<p>We set the dominos rolling in <code class="docutils literal notranslate"><span class="pre">main()</span></code>:</p>
<p class="rubric">uvcat/main.c</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7
8
9</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">main</span><span class="p">(</span><span class="nb">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
<span class="hll">    <span class="n">uv_fs_open</span><span class="p">(</span><span class="n">uv_default_loop</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">open_req</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">O_RDONLY</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">on_open</span><span class="p">);</span>
</span>    <span class="n">uv_run</span><span class="p">(</span><span class="n">uv_default_loop</span><span class="p">(),</span> <span class="n">UV_RUN_DEFAULT</span><span class="p">);</span>

    <span class="n">uv_fs_req_cleanup</span><span class="p">(</span><span class="o">&amp;</span><span class="n">open_req</span><span class="p">);</span>
    <span class="n">uv_fs_req_cleanup</span><span class="p">(</span><span class="o">&amp;</span><span class="n">read_req</span><span class="p">);</span>
    <span class="n">uv_fs_req_cleanup</span><span class="p">(</span><span class="o">&amp;</span><span class="n">write_req</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>The <code class="docutils literal notranslate"><span class="pre">uv_fs_req_cleanup()</span></code> function must always be called on filesystem
requests to free internal memory allocations in libuv.</p>
</div>
</div>
<div class="section" id="filesystem-operations">
<h2>Filesystem operations<a class="headerlink" href="#filesystem-operations" title="Permalink to this headline">¶</a></h2>
<p>All the standard filesystem operations like <code class="docutils literal notranslate"><span class="pre">unlink</span></code>, <code class="docutils literal notranslate"><span class="pre">rmdir</span></code>, <code class="docutils literal notranslate"><span class="pre">stat</span></code> are
supported asynchronously and have intuitive argument order. They follow the
same patterns as the read/write/open calls, returning the result in the
<code class="docutils literal notranslate"><span class="pre">uv_fs_t.result</span></code> field. The full list:</p>
<p class="rubric">Filesystem operations</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">};</span>

<span class="n">typedef</span> <span class="n">enum</span> <span class="p">{</span>
  <span class="n">UV_DIRENT_UNKNOWN</span><span class="p">,</span>
  <span class="n">UV_DIRENT_FILE</span><span class="p">,</span>
  <span class="n">UV_DIRENT_DIR</span><span class="p">,</span>
  <span class="n">UV_DIRENT_LINK</span><span class="p">,</span>
  <span class="n">UV_DIRENT_FIFO</span><span class="p">,</span>
  <span class="n">UV_DIRENT_SOCKET</span><span class="p">,</span>
  <span class="n">UV_DIRENT_CHAR</span><span class="p">,</span>
  <span class="n">UV_DIRENT_BLOCK</span>
<span class="p">}</span> <span class="n">uv_dirent_type_t</span><span class="p">;</span>

<span class="n">struct</span> <span class="n">uv_dirent_s</span> <span class="p">{</span>
  <span class="n">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">;</span>
  <span class="n">uv_dirent_type_t</span> <span class="nb">type</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">UV_EXTERN</span> <span class="n">char</span><span class="o">**</span> <span class="n">uv_setup_args</span><span class="p">(</span><span class="nb">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span><span class="o">**</span> <span class="n">argv</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_get_process_title</span><span class="p">(</span><span class="n">char</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_set_process_title</span><span class="p">(</span><span class="n">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">title</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_resident_set_memory</span><span class="p">(</span><span class="n">size_t</span><span class="o">*</span> <span class="n">rss</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_uptime</span><span class="p">(</span><span class="n">double</span><span class="o">*</span> <span class="n">uptime</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="n">uv_os_fd_t</span> <span class="n">uv_get_osfhandle</span><span class="p">(</span><span class="nb">int</span> <span class="n">fd</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_open_osfhandle</span><span class="p">(</span><span class="n">uv_os_fd_t</span> <span class="n">os_fd</span><span class="p">);</span>

<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
  <span class="n">long</span> <span class="n">tv_sec</span><span class="p">;</span>
  <span class="n">long</span> <span class="n">tv_usec</span><span class="p">;</span>
<span class="p">}</span> <span class="n">uv_timeval_t</span><span class="p">;</span>

<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
  <span class="n">int64_t</span> <span class="n">tv_sec</span><span class="p">;</span>
  <span class="n">int32_t</span> <span class="n">tv_usec</span><span class="p">;</span>
<span class="p">}</span> <span class="n">uv_timeval64_t</span><span class="p">;</span>

<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
   <span class="n">uv_timeval_t</span> <span class="n">ru_utime</span><span class="p">;</span> <span class="o">/*</span> <span class="n">user</span> <span class="n">CPU</span> <span class="n">time</span> <span class="n">used</span> <span class="o">*/</span>
   <span class="n">uv_timeval_t</span> <span class="n">ru_stime</span><span class="p">;</span> <span class="o">/*</span> <span class="n">system</span> <span class="n">CPU</span> <span class="n">time</span> <span class="n">used</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_maxrss</span><span class="p">;</span>    <span class="o">/*</span> <span class="n">maximum</span> <span class="n">resident</span> <span class="nb">set</span> <span class="n">size</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_ixrss</span><span class="p">;</span>     <span class="o">/*</span> <span class="n">integral</span> <span class="n">shared</span> <span class="n">memory</span> <span class="n">size</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_idrss</span><span class="p">;</span>     <span class="o">/*</span> <span class="n">integral</span> <span class="n">unshared</span> <span class="n">data</span> <span class="n">size</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_isrss</span><span class="p">;</span>     <span class="o">/*</span> <span class="n">integral</span> <span class="n">unshared</span> <span class="n">stack</span> <span class="n">size</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_minflt</span><span class="p">;</span>    <span class="o">/*</span> <span class="n">page</span> <span class="n">reclaims</span> <span class="p">(</span><span class="n">soft</span> <span class="n">page</span> <span class="n">faults</span><span class="p">)</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_majflt</span><span class="p">;</span>    <span class="o">/*</span> <span class="n">page</span> <span class="n">faults</span> <span class="p">(</span><span class="n">hard</span> <span class="n">page</span> <span class="n">faults</span><span class="p">)</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_nswap</span><span class="p">;</span>     <span class="o">/*</span> <span class="n">swaps</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_inblock</span><span class="p">;</span>   <span class="o">/*</span> <span class="n">block</span> <span class="nb">input</span> <span class="n">operations</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_oublock</span><span class="p">;</span>   <span class="o">/*</span> <span class="n">block</span> <span class="n">output</span> <span class="n">operations</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_msgsnd</span><span class="p">;</span>    <span class="o">/*</span> <span class="n">IPC</span> <span class="n">messages</span> <span class="n">sent</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_msgrcv</span><span class="p">;</span>    <span class="o">/*</span> <span class="n">IPC</span> <span class="n">messages</span> <span class="n">received</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_nsignals</span><span class="p">;</span>  <span class="o">/*</span> <span class="n">signals</span> <span class="n">received</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_nvcsw</span><span class="p">;</span>     <span class="o">/*</span> <span class="n">voluntary</span> <span class="n">context</span> <span class="n">switches</span> <span class="o">*/</span>
   <span class="n">uint64_t</span> <span class="n">ru_nivcsw</span><span class="p">;</span>    <span class="o">/*</span> <span class="n">involuntary</span> <span class="n">context</span> <span class="n">switches</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">uv_rusage_t</span><span class="p">;</span>

<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_getrusage</span><span class="p">(</span><span class="n">uv_rusage_t</span><span class="o">*</span> <span class="n">rusage</span><span class="p">);</span>

<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_homedir</span><span class="p">(</span><span class="n">char</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size_t</span><span class="o">*</span> <span class="n">size</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_tmpdir</span><span class="p">(</span><span class="n">char</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size_t</span><span class="o">*</span> <span class="n">size</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_get_passwd</span><span class="p">(</span><span class="n">uv_passwd_t</span><span class="o">*</span> <span class="n">pwd</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="n">void</span> <span class="n">uv_os_free_passwd</span><span class="p">(</span><span class="n">uv_passwd_t</span><span class="o">*</span> <span class="n">pwd</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="n">uv_pid_t</span> <span class="n">uv_os_getpid</span><span class="p">(</span><span class="n">void</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="n">uv_pid_t</span> <span class="n">uv_os_getppid</span><span class="p">(</span><span class="n">void</span><span class="p">);</span>

<span class="c1">#define UV_PRIORITY_LOW 19</span>
<span class="c1">#define UV_PRIORITY_BELOW_NORMAL 10</span>
<span class="c1">#define UV_PRIORITY_NORMAL 0</span>
<span class="c1">#define UV_PRIORITY_ABOVE_NORMAL -7</span>
<span class="c1">#define UV_PRIORITY_HIGH -14</span>
<span class="c1">#define UV_PRIORITY_HIGHEST -20</span>

<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_getpriority</span><span class="p">(</span><span class="n">uv_pid_t</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">int</span><span class="o">*</span> <span class="n">priority</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_setpriority</span><span class="p">(</span><span class="n">uv_pid_t</span> <span class="n">pid</span><span class="p">,</span> <span class="nb">int</span> <span class="n">priority</span><span class="p">);</span>

<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_cpu_info</span><span class="p">(</span><span class="n">uv_cpu_info_t</span><span class="o">**</span> <span class="n">cpu_infos</span><span class="p">,</span> <span class="nb">int</span><span class="o">*</span> <span class="n">count</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="n">void</span> <span class="n">uv_free_cpu_info</span><span class="p">(</span><span class="n">uv_cpu_info_t</span><span class="o">*</span> <span class="n">cpu_infos</span><span class="p">,</span> <span class="nb">int</span> <span class="n">count</span><span class="p">);</span>

<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_interface_addresses</span><span class="p">(</span><span class="n">uv_interface_address_t</span><span class="o">**</span> <span class="n">addresses</span><span class="p">,</span>
                                     <span class="nb">int</span><span class="o">*</span> <span class="n">count</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="n">void</span> <span class="n">uv_free_interface_addresses</span><span class="p">(</span><span class="n">uv_interface_address_t</span><span class="o">*</span> <span class="n">addresses</span><span class="p">,</span>
                                           <span class="nb">int</span> <span class="n">count</span><span class="p">);</span>

<span class="n">struct</span> <span class="n">uv_env_item_s</span> <span class="p">{</span>
  <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">;</span>
  <span class="n">char</span><span class="o">*</span> <span class="n">value</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_environ</span><span class="p">(</span><span class="n">uv_env_item_t</span><span class="o">**</span> <span class="n">envitems</span><span class="p">,</span> <span class="nb">int</span><span class="o">*</span> <span class="n">count</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="n">void</span> <span class="n">uv_os_free_environ</span><span class="p">(</span><span class="n">uv_env_item_t</span><span class="o">*</span> <span class="n">envitems</span><span class="p">,</span> <span class="nb">int</span> <span class="n">count</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_getenv</span><span class="p">(</span><span class="n">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> <span class="n">char</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size_t</span><span class="o">*</span> <span class="n">size</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_setenv</span><span class="p">(</span><span class="n">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">value</span><span class="p">);</span>
<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_unsetenv</span><span class="p">(</span><span class="n">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">name</span><span class="p">);</span>

<span class="c1">#ifdef MAXHOSTNAMELEN</span>
<span class="c1"># define UV_MAXHOSTNAMESIZE (MAXHOSTNAMELEN + 1)</span>
<span class="c1">#else</span>
  <span class="o">/*</span>
    <span class="n">Fallback</span> <span class="k">for</span> <span class="n">the</span> <span class="n">maximum</span> <span class="n">hostname</span> <span class="n">size</span><span class="p">,</span> <span class="n">including</span> <span class="n">the</span> <span class="n">null</span> <span class="n">terminator</span><span class="o">.</span> <span class="n">The</span>
    <span class="n">Windows</span> <span class="n">gethostname</span><span class="p">()</span> <span class="n">documentation</span> <span class="n">states</span> <span class="n">that</span> <span class="mi">256</span> <span class="nb">bytes</span> <span class="n">will</span> <span class="n">always</span> <span class="n">be</span>
    <span class="n">large</span> <span class="n">enough</span> <span class="n">to</span> <span class="n">hold</span> <span class="n">the</span> <span class="n">null</span><span class="o">-</span><span class="n">terminated</span> <span class="n">hostname</span><span class="o">.</span>
  <span class="o">*/</span>
<span class="c1"># define UV_MAXHOSTNAMESIZE 256</span>
<span class="c1">#endif</span>

<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_gethostname</span><span class="p">(</span><span class="n">char</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size_t</span><span class="o">*</span> <span class="n">size</span><span class="p">);</span>

<span class="n">UV_EXTERN</span> <span class="nb">int</span> <span class="n">uv_os_uname</span><span class="p">(</span><span class="n">uv_utsname_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">);</span>


<span class="n">typedef</span> <span class="n">enum</span> <span class="p">{</span>
  <span class="n">UV_FS_UNKNOWN</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
  <span class="n">UV_FS_CUSTOM</span><span class="p">,</span>
</pre></div>
</div>
</div>
<div class="section" id="buffers-and-streams">
<span id="id1"></span><h2>Buffers and Streams<a class="headerlink" href="#buffers-and-streams" title="Permalink to this headline">¶</a></h2>
<p>The basic I/O handle in libuv is the stream (<code class="docutils literal notranslate"><span class="pre">uv_stream_t</span></code>). TCP sockets, UDP
sockets, and pipes for file I/O and IPC are all treated as stream subclasses.</p>
<p>Streams are initialized using custom functions for each subclass, then operated
upon using</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span> <span class="nf">uv_read_start</span><span class="p">(</span><span class="n">uv_stream_t</span><span class="o">*</span><span class="p">,</span> <span class="n">uv_alloc_cb</span> <span class="n">alloc_cb</span><span class="p">,</span> <span class="n">uv_read_cb</span> <span class="n">read_cb</span><span class="p">);</span>
<span class="kt">int</span> <span class="nf">uv_read_stop</span><span class="p">(</span><span class="n">uv_stream_t</span><span class="o">*</span><span class="p">);</span>
<span class="kt">int</span> <span class="nf">uv_write</span><span class="p">(</span><span class="n">uv_write_t</span><span class="o">*</span> <span class="n">req</span><span class="p">,</span> <span class="n">uv_stream_t</span><span class="o">*</span> <span class="n">handle</span><span class="p">,</span>
             <span class="k">const</span> <span class="n">uv_buf_t</span> <span class="n">bufs</span><span class="p">[],</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">nbufs</span><span class="p">,</span> <span class="n">uv_write_cb</span> <span class="n">cb</span><span class="p">);</span>
</pre></div>
</div>
<p>The stream based functions are simpler to use than the filesystem ones and
libuv will automatically keep reading from a stream when <code class="docutils literal notranslate"><span class="pre">uv_read_start()</span></code> is
called once, until <code class="docutils literal notranslate"><span class="pre">uv_read_stop()</span></code> is called.</p>
<p>The discrete unit of data is the buffer – <code class="docutils literal notranslate"><span class="pre">uv_buf_t</span></code>. This is simply
a collection of a pointer to bytes (<code class="docutils literal notranslate"><span class="pre">uv_buf_t.base</span></code>) and the length
(<code class="docutils literal notranslate"><span class="pre">uv_buf_t.len</span></code>). The <code class="docutils literal notranslate"><span class="pre">uv_buf_t</span></code> is lightweight and passed around by value.
What does require management is the actual bytes, which have to be allocated
and freed by the application.</p>
<div class="admonition error">
<p class="admonition-title">Error</p>
<p>THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER**</p>
</div>
<p>To demonstrate streams we will need to use <code class="docutils literal notranslate"><span class="pre">uv_pipe_t</span></code>. This allows streaming
local files <a class="footnote-reference brackets" href="#id4" id="id2">2</a>. Here is a simple tee utility using libuv.  Doing all operations
asynchronously shows the power of evented I/O. The two writes won’t block each
other, but we have to be careful to copy over the buffer data to ensure we don’t
free a buffer until it has been written.</p>
<p>The program is to be executed as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">./</span><span class="n">uvtee</span> <span class="o">&lt;</span><span class="n">output_file</span><span class="o">&gt;</span>
</pre></div>
</div>
<p>We start off opening pipes on the files we require. libuv pipes to a file are
opened as bidirectional by default.</p>
<p class="rubric">uvtee/main.c - read on pipes</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<span class="nb">int</span> <span class="n">main</span><span class="p">(</span><span class="nb">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">loop</span> <span class="o">=</span> <span class="n">uv_default_loop</span><span class="p">();</span>
<span class="hll">
</span><span class="hll">    <span class="n">uv_pipe_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">stdin_pipe</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span>    <span class="n">uv_pipe_open</span><span class="p">(</span><span class="o">&amp;</span><span class="n">stdin_pipe</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">uv_pipe_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">stdout_pipe</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">uv_pipe_open</span><span class="p">(</span><span class="o">&amp;</span><span class="n">stdout_pipe</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
    
    <span class="n">uv_fs_t</span> <span class="n">file_req</span><span class="p">;</span>
    <span class="nb">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">uv_fs_open</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">file_req</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_RDWR</span><span class="p">,</span> <span class="mi">0644</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span>
    <span class="n">uv_pipe_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">file_pipe</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">uv_pipe_open</span><span class="p">(</span><span class="o">&amp;</span><span class="n">file_pipe</span><span class="p">,</span> <span class="n">fd</span><span class="p">);</span>
<span class="hll">
</span>    <span class="n">uv_read_start</span><span class="p">((</span><span class="n">uv_stream_t</span><span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">stdin_pipe</span><span class="p">,</span> <span class="n">alloc_buffer</span><span class="p">,</span> <span class="n">read_stdin</span><span class="p">);</span>

    <span class="n">uv_run</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="n">UV_RUN_DEFAULT</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The third argument of <code class="docutils literal notranslate"><span class="pre">uv_pipe_init()</span></code> should be set to 1 for IPC using named
pipes. This is covered in <a class="reference internal" href="processes.html"><span class="doc">Processes</span></a>. The <code class="docutils literal notranslate"><span class="pre">uv_pipe_open()</span></code> call
associates the pipe with the file descriptor, in this case <code class="docutils literal notranslate"><span class="pre">0</span></code> (standard
input).</p>
<p>We start monitoring <code class="docutils literal notranslate"><span class="pre">stdin</span></code>. The <code class="docutils literal notranslate"><span class="pre">alloc_buffer</span></code> callback is invoked as new
buffers are required to hold incoming data. <code class="docutils literal notranslate"><span class="pre">read_stdin</span></code> will be called with
these buffers.</p>
<p class="rubric">uvtee/main.c - reading buffers</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">alloc_buffer</span><span class="p">(</span><span class="n">uv_handle_t</span> <span class="o">*</span><span class="n">handle</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">suggested_size</span><span class="p">,</span> <span class="n">uv_buf_t</span> <span class="o">*</span><span class="n">buf</span><span class="p">)</span> <span class="p">{</span>
    <span class="o">*</span><span class="n">buf</span> <span class="o">=</span> <span class="n">uv_buf_init</span><span class="p">((</span><span class="n">char</span><span class="o">*</span><span class="p">)</span> <span class="n">malloc</span><span class="p">(</span><span class="n">suggested_size</span><span class="p">),</span> <span class="n">suggested_size</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">void</span> <span class="n">read_stdin</span><span class="p">(</span><span class="n">uv_stream_t</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">ssize_t</span> <span class="n">nread</span><span class="p">,</span> <span class="n">const</span> <span class="n">uv_buf_t</span> <span class="o">*</span><span class="n">buf</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">nread</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">){</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">nread</span> <span class="o">==</span> <span class="n">UV_EOF</span><span class="p">){</span>
            <span class="o">//</span> <span class="n">end</span> <span class="n">of</span> <span class="n">file</span>
            <span class="n">uv_close</span><span class="p">((</span><span class="n">uv_handle_t</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">stdin_pipe</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span>
            <span class="n">uv_close</span><span class="p">((</span><span class="n">uv_handle_t</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">stdout_pipe</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span>
            <span class="n">uv_close</span><span class="p">((</span><span class="n">uv_handle_t</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">file_pipe</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">nread</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">write_data</span><span class="p">((</span><span class="n">uv_stream_t</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">stdout_pipe</span><span class="p">,</span> <span class="n">nread</span><span class="p">,</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="n">on_stdout_write</span><span class="p">);</span>
        <span class="n">write_data</span><span class="p">((</span><span class="n">uv_stream_t</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">file_pipe</span><span class="p">,</span> <span class="n">nread</span><span class="p">,</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="n">on_file_write</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="o">//</span> <span class="n">OK</span> <span class="n">to</span> <span class="n">free</span> <span class="n">buffer</span> <span class="k">as</span> <span class="n">write_data</span> <span class="n">copies</span> <span class="n">it</span><span class="o">.</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="o">-&gt;</span><span class="n">base</span><span class="p">)</span>
        <span class="n">free</span><span class="p">(</span><span class="n">buf</span><span class="o">-&gt;</span><span class="n">base</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The standard <code class="docutils literal notranslate"><span class="pre">malloc</span></code> is sufficient here, but you can use any memory allocation
scheme. For example, node.js uses its own slab allocator which associates
buffers with V8 objects.</p>
<p>The read callback <code class="docutils literal notranslate"><span class="pre">nread</span></code> parameter is less than 0 on any error. This error
might be EOF, in which case we close all the streams, using the generic close
function <code class="docutils literal notranslate"><span class="pre">uv_close()</span></code> which deals with the handle based on its internal type.
Otherwise <code class="docutils literal notranslate"><span class="pre">nread</span></code> is a non-negative number and we can attempt to write that
many bytes to the output streams. Finally remember that buffer allocation and
deallocation is application responsibility, so we free the data.</p>
<p>The allocation callback may return a buffer with length zero if it fails to
allocate memory. In this case, the read callback is invoked with error
UV_ENOBUFS. libuv will continue to attempt to read the stream though, so you
must explicitly call <code class="docutils literal notranslate"><span class="pre">uv_close()</span></code> if you want to stop when allocation fails.</p>
<p>The read callback may be called with <code class="docutils literal notranslate"><span class="pre">nread</span> <span class="pre">=</span> <span class="pre">0</span></code>, indicating that at this
point there is nothing to be read. Most applications will just ignore this.</p>
<p class="rubric">uvtee/main.c - Write to pipe</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
    <span class="n">uv_write_t</span> <span class="n">req</span><span class="p">;</span>
    <span class="n">uv_buf_t</span> <span class="n">buf</span><span class="p">;</span>
<span class="p">}</span> <span class="n">write_req_t</span><span class="p">;</span>

<span class="n">void</span> <span class="n">free_write_req</span><span class="p">(</span><span class="n">uv_write_t</span> <span class="o">*</span><span class="n">req</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">write_req_t</span> <span class="o">*</span><span class="n">wr</span> <span class="o">=</span> <span class="p">(</span><span class="n">write_req_t</span><span class="o">*</span><span class="p">)</span> <span class="n">req</span><span class="p">;</span>
    <span class="n">free</span><span class="p">(</span><span class="n">wr</span><span class="o">-&gt;</span><span class="n">buf</span><span class="o">.</span><span class="n">base</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">wr</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">void</span> <span class="n">on_stdout_write</span><span class="p">(</span><span class="n">uv_write_t</span> <span class="o">*</span><span class="n">req</span><span class="p">,</span> <span class="nb">int</span> <span class="n">status</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">free_write_req</span><span class="p">(</span><span class="n">req</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">void</span> <span class="n">on_file_write</span><span class="p">(</span><span class="n">uv_write_t</span> <span class="o">*</span><span class="n">req</span><span class="p">,</span> <span class="nb">int</span> <span class="n">status</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">free_write_req</span><span class="p">(</span><span class="n">req</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">void</span> <span class="n">write_data</span><span class="p">(</span><span class="n">uv_stream_t</span> <span class="o">*</span><span class="n">dest</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="n">uv_buf_t</span> <span class="n">buf</span><span class="p">,</span> <span class="n">uv_write_cb</span> <span class="n">cb</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">write_req_t</span> <span class="o">*</span><span class="n">req</span> <span class="o">=</span> <span class="p">(</span><span class="n">write_req_t</span><span class="o">*</span><span class="p">)</span> <span class="n">malloc</span><span class="p">(</span><span class="n">sizeof</span><span class="p">(</span><span class="n">write_req_t</span><span class="p">));</span>
    <span class="n">req</span><span class="o">-&gt;</span><span class="n">buf</span> <span class="o">=</span> <span class="n">uv_buf_init</span><span class="p">((</span><span class="n">char</span><span class="o">*</span><span class="p">)</span> <span class="n">malloc</span><span class="p">(</span><span class="n">size</span><span class="p">),</span> <span class="n">size</span><span class="p">);</span>
    <span class="n">memcpy</span><span class="p">(</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">buf</span><span class="o">.</span><span class="n">base</span><span class="p">,</span> <span class="n">buf</span><span class="o">.</span><span class="n">base</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
    <span class="n">uv_write</span><span class="p">((</span><span class="n">uv_write_t</span><span class="o">*</span><span class="p">)</span> <span class="n">req</span><span class="p">,</span> <span class="p">(</span><span class="n">uv_stream_t</span><span class="o">*</span><span class="p">)</span><span class="n">dest</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">req</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">cb</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p><code class="docutils literal notranslate"><span class="pre">write_data()</span></code> makes a copy of the buffer obtained from read. This buffer
does not get passed through to the write callback trigged on write completion. To
get around this we wrap a write request and a buffer in <code class="docutils literal notranslate"><span class="pre">write_req_t</span></code> and
unwrap it in the callbacks. We make a copy so we can free the two buffers from
the two calls to <code class="docutils literal notranslate"><span class="pre">write_data</span></code> independently of each other. While acceptable
for a demo program like this, you’ll probably want smarter memory management,
like reference counted buffers or a pool of buffers in any major application.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>If your program is meant to be used with other programs it may knowingly or
unknowingly be writing to a pipe. This makes it susceptible to <a class="reference external" href="http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_special_problem_of_SIGPIPE">aborting on
receiving a SIGPIPE</a>. It is a good idea to insert:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">signal</span><span class="p">(</span><span class="n">SIGPIPE</span><span class="p">,</span> <span class="n">SIG_IGN</span><span class="p">)</span>
</pre></div>
</div>
<p>in the initialization stages of your application.</p>
</div>
</div>
<div class="section" id="file-change-events">
<h2>File change events<a class="headerlink" href="#file-change-events" title="Permalink to this headline">¶</a></h2>
<p>All modern operating systems provide APIs to put watches on individual files or
directories and be informed when the files are modified. libuv wraps common
file change notification libraries <a class="footnote-reference brackets" href="#fsnotify" id="id3">1</a>. This is one of the more
inconsistent parts of libuv. File change notification systems are themselves
extremely varied across platforms so getting everything working everywhere is
difficult. To demonstrate, I’m going to build a simple utility which runs
a command whenever any of the watched files change:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">./</span><span class="n">onchange</span> <span class="o">&lt;</span><span class="n">command</span><span class="o">&gt;</span> <span class="o">&lt;</span><span class="n">file1</span><span class="o">&gt;</span> <span class="p">[</span><span class="n">file2</span><span class="p">]</span> <span class="o">...</span>
</pre></div>
</div>
<p>The file change notification is started using <code class="docutils literal notranslate"><span class="pre">uv_fs_event_init()</span></code>:</p>
<p class="rubric">onchange/main.c - The setup</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">main</span><span class="p">(</span><span class="nb">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&lt;=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Usage: </span><span class="si">%s</span><span class="s2"> &lt;command&gt; &lt;file1&gt; [file2 ...]</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">loop</span> <span class="o">=</span> <span class="n">uv_default_loop</span><span class="p">();</span>
    <span class="n">command</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>

    <span class="k">while</span> <span class="p">(</span><span class="n">argc</span><span class="o">--</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Adding watch on </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="n">argc</span><span class="p">]);</span>
        <span class="n">uv_fs_event_t</span> <span class="o">*</span><span class="n">fs_event_req</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">sizeof</span><span class="p">(</span><span class="n">uv_fs_event_t</span><span class="p">));</span>
        <span class="n">uv_fs_event_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="n">fs_event_req</span><span class="p">);</span>
        <span class="o">//</span> <span class="n">The</span> <span class="n">recursive</span> <span class="n">flag</span> <span class="n">watches</span> <span class="n">subdirectories</span> <span class="n">too</span><span class="o">.</span>
<span class="hll">        <span class="n">uv_fs_event_start</span><span class="p">(</span><span class="n">fs_event_req</span><span class="p">,</span> <span class="n">run_command</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="n">argc</span><span class="p">],</span> <span class="n">UV_FS_EVENT_RECURSIVE</span><span class="p">);</span>
</span>    <span class="p">}</span>

    <span class="k">return</span> <span class="n">uv_run</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="n">UV_RUN_DEFAULT</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The third argument is the actual file or directory to monitor. The last
argument, <code class="docutils literal notranslate"><span class="pre">flags</span></code>, can be:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/*</span>
                             <span class="n">const</span> <span class="n">char</span><span class="o">*</span> <span class="n">new_path</span><span class="p">,</span>
                          <span class="n">uv_fs_cb</span> <span class="n">cb</span><span class="p">);</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">UV_FS_EVENT_WATCH_ENTRY</span></code> and <code class="docutils literal notranslate"><span class="pre">UV_FS_EVENT_STAT</span></code> don’t do anything (yet).
<code class="docutils literal notranslate"><span class="pre">UV_FS_EVENT_RECURSIVE</span></code> will start watching subdirectories as well on
supported platforms.</p>
<p>The callback will receive the following arguments:</p>
<blockquote>
<div><ol class="arabic simple">
<li><p><code class="docutils literal notranslate"><span class="pre">uv_fs_event_t</span> <span class="pre">*handle</span></code> - The handle. The <code class="docutils literal notranslate"><span class="pre">path</span></code> field of the handle
is the file on which the watch was set.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*filename</span></code> - If a directory is being monitored, this is the
file which was changed. Only non-<code class="docutils literal notranslate"><span class="pre">null</span></code> on Linux and Windows. May be <code class="docutils literal notranslate"><span class="pre">null</span></code>
even on those platforms.</p></li>
<li><dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">flags</span></code> - one of <code class="docutils literal notranslate"><span class="pre">UV_RENAME</span></code> or <code class="docutils literal notranslate"><span class="pre">UV_CHANGE</span></code>, or a bitwise OR of</dt><dd><p>both.</p>
</dd>
</dl>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">status</span></code> - Currently 0.</p></li>
</ol>
</div></blockquote>
<p>In our example we simply print the arguments and run the command using
<code class="docutils literal notranslate"><span class="pre">system()</span></code>.</p>
<p class="rubric">onchange/main.c - file change notification callback</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16</pre></div></td><td class="code"><div class="highlight"><pre><span></span>void run_command(uv_fs_event_t *handle, const char *filename, int events, int status) {
    char path[1024];
    size_t size = 1023;
    // Does not handle error if path is longer than 1023.
    uv_fs_event_getpath(handle, path, &amp;size);
    path[size] = &#39;\0&#39;;

    fprintf(stderr, &quot;Change detected in %s: &quot;, path);
    if (events &amp; UV_RENAME)
        fprintf(stderr, &quot;renamed&quot;);
    if (events &amp; UV_CHANGE)
        fprintf(stderr, &quot;changed&quot;);

    fprintf(stderr, &quot; %s\n&quot;, filename ? filename : &quot;&quot;);
    system(command);
}
</pre></div>
</td></tr></table></div>
<hr class="docutils" />
<dl class="footnote brackets">
<dt class="label" id="fsnotify"><span class="brackets"><a class="fn-backref" href="#id3">1</a></span></dt>
<dd><p>inotify on Linux, FSEvents on Darwin, kqueue on BSDs,
ReadDirectoryChangesW on Windows, event ports on Solaris, unsupported on Cygwin</p>
</dd>
<dt class="label" id="id4"><span class="brackets"><a class="fn-backref" href="#id2">2</a></span></dt>
<dd><p>see <a class="reference internal" href="processes.html#pipes"><span class="std std-ref">Pipes</span></a></p>
</dd>
</dl>
</div>
</div>


            <div class="clearer"></div>
          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
            <p class="logo"><a href="../index.html">
              <img class="logo" src="../_static/logo.png" alt="Logo"/>
            </a></p>
  <h3><a href="../index.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Filesystem</a><ul>
<li><a class="reference internal" href="#reading-writing-files">Reading/Writing files</a></li>
<li><a class="reference internal" href="#filesystem-operations">Filesystem operations</a></li>
<li><a class="reference internal" href="#buffers-and-streams">Buffers and Streams</a></li>
<li><a class="reference internal" href="#file-change-events">File change events</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="basics.html"
                        title="previous chapter">Basics of libuv</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="networking.html"
                        title="next chapter">Networking</a></p>
  <div role="note" aria-label="source link">
    <h3>This Page</h3>
    <ul class="this-page-menu">
      <li><a href="../_sources/guide/filesystem.rst.txt"
            rel="nofollow">Show Source</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3 id="searchlabel">Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" aria-labelledby="searchlabel" />
      <input type="submit" value="Go" />
    </form>
    </div>
</div>
<script>$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="networking.html" title="Networking"
             >next</a> |</li>
        <li class="right" >
          <a href="basics.html" title="Basics of libuv"
             >previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="../index.html">libuv 1.31.0 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../guide.html" >User guide</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Filesystem</a></li> 
      </ul>
    </div>
    <div class="footer" role="contentinfo">
        &#169; Copyright 2014-present, libuv contributors.
      Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
    </div>
  </body>
</html>